# -*- coding: utf-8 -*-
# @#Time : 2021/8/18 18:44

# @File : yb_gy_autoSubmit.py
# @Software : PyCharm
import base64
import json
import os
import platform
import random
import re
import sys
import time
import urllib.parse
from pathlib import Path
from urllib.parse import urlencode



# 第三方库
from jsmin import jsmin

try:
    import requests
except ModuleNotFoundError:
    print("缺少requests依赖！程序将尝试安装依赖！")
    os.system("pip3 install requests -i https://pypi.tuna.tsinghua.edu.cn/simple")
    os.execl(sys.executable, 'python3', __file__, *sys.argv[1:]) \
        if platform.system() == "Linux" else os.system(
        "cls") if platform.system() == "Windows" else print("未知操作系统，可能需要重新运行！")

try:
    from Crypto.Cipher import PKCS1_v1_5
    from Crypto.PublicKey import RSA
except ModuleNotFoundError:
    print("缺少pycryptodome依赖！程序将尝试安装依赖！")
    os.system("pip3 install pycryptodome -i https://pypi.tuna.tsinghua.edu.cn/simple")
    os.execl(sys.executable, 'python3', __file__, *sys.argv[1:]) if platform.system() == "Linux" else os.system(
        "cls") if platform.system() == "Windows" else print("未知操作系统，可能需要重新运行！")

# from config import accounts
# import requests as requests
# from Crypto.Cipher import PKCS1_v1_5
# from Crypto.PublicKey import RSA

'''改变工作目录开始'''
my_dir = os.path.split(os.path.realpath(__file__))[0]
workdir_name = 'my_work_dir'
workdir = my_dir + os.sep + workdir_name
if os.getcwd() != my_dir:
    os.chdir(my_dir)
if not Path(workdir).is_dir():
    os.mkdir(workdir_name)
'''改变工作目录结束'''


def save_access_token(access_token):
    try:
        my_access_token = Path(workdir + os.sep + "access_token")
        if not my_access_token.is_file():
            with open(workdir + os.sep + "access_token", 'w', encoding='utf-8') as token:
                token.write(access_token)
        print('token保存成功，下次可以快速登录')
    except Exception as err:
        print("出错啦%s" % err)


def read_access_token():
    try:
        my_access_token = Path(workdir + os.sep + "access_token")
        if my_access_token.is_file():
            with open(workdir + os.sep + "access_token", 'r', encoding='utf-8') as token:
                token_f = token.read()
            return token_f

        return -1
    except Exception as err:
        print("读取token出错，使用密码登录\n%s" % err)
        return -1


def main(accounts):
    for each in accounts:
        if each['account'] != "" and each['password'] != "":
            yiBan = YiBan(each)
            for count in range(1):
                # try:
                time.sleep(random.randint(2, 5))  # 随机延时
                print("请不要在身体不适时使用该脚本")

                Path()
                if Path(workdir + os.sep + "access_token").is_file():
                    return yiBan.auto_login()
                yiBan.login()
                # os.system("pause")
                # input("回车键退出")


        else:
            print("账号密码未填写")


class YiBan:
    def __init__(self, dic):

        self.dic = dic
        self.sess = requests.Session()
        self.csrf = ''.join(random.sample('zyxwvutsrqponmlkjihgfedcba0123456789', 32))
        self.sess.cookies.update({"csrf_token": self.csrf})

    def getName(self):
        if self.dic['remark'] != "":
            return self.dic['remark']

        return self.dic['account']

    def encryptPassword(self, pwd):
        # 密码加密
        PUBLIC_KEY = '''-----BEGIN PUBLIC KEY-----
            MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA6aTDM8BhCS8O0wlx2KzA
            Ajffez4G4A/QSnn1ZDuvLRbKBHm0vVBtBhD03QUnnHXvqigsOOwr4onUeNljegIC
            XC9h5exLFidQVB58MBjItMA81YVlZKBY9zth1neHeRTWlFTCx+WasvbS0HuYpF8+
            KPl7LJPjtI4XAAOLBntQGnPwCX2Ff/LgwqkZbOrHHkN444iLmViCXxNUDUMUR9bP
            A9/I5kwfyZ/mM5m8+IPhSXZ0f2uw1WLov1P4aeKkaaKCf5eL3n7/2vgq7kw2qSmR
            AGBZzW45PsjOEvygXFOy2n7AXL9nHogDiMdbe4aY2VT70sl0ccc4uvVOvVBMinOp
            d2rEpX0/8YE0dRXxukrM7i+r6lWy1lSKbP+0tQxQHNa/Cjg5W3uU+W9YmNUFc1w/
            7QT4SZrnRBEo++Xf9D3YNaOCFZXhy63IpY4eTQCJFQcXdnRbTXEdC3CtWNd7SV/h
            mfJYekb3GEV+10xLOvpe/+tCTeCDpFDJP6UuzLXBBADL2oV3D56hYlOlscjBokNU
            AYYlWgfwA91NjDsWW9mwapm/eLs4FNyH0JcMFTWH9dnl8B7PCUra/Lg/IVv6HkFE
            uCL7hVXGMbw2BZuCIC2VG1ZQ6QD64X8g5zL+HDsusQDbEJV2ZtojalTIjpxMksbR
            ZRsH+P3+NNOZOEwUdjJUAx8CAwEAAQ==
            -----END PUBLIC KEY-----'''
        cipher = PKCS1_v1_5.new(RSA.importKey(PUBLIC_KEY))
        cipher_text = base64.b64encode(cipher.encrypt(bytes(pwd, encoding="utf8")))
        return cipher_text.decode("utf-8")

    def login(self):
        url = "https://m.yiban.cn/api/v4/passport/login"
        param = {
            "device": "Xiaomi:M2007J3SC",
            "v": "5.0.1",
            "mobile": int(self.dic['account']),
            "password": self.encryptPassword(self.dic['password']),
            "token": "",
            "ct": "2",
            "identify": "0",
            "sversion": "29",
            "app": "1",
            "apn": "wifi",
            "authCode": "",
            "sig": "bce63f9037c5979e"
        }
        header = {
            # 'Origin': 'https://m.yiban.cn',
            'User-Agent': 'YiBan/5.0.1 Mozilla/5.0 (Linux; Android 10; M2007J3SC Build/QKQ1.200419.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/83.0.4103.101 Mobile Safari/537.36',
            'Referer': 'https://m.yiban.cn',
            'AppVersion': '5.0.1'
        }

        response = self.sess.post(url=url, params=param, headers=header).text
        response = json.loads(response)
        # print(response)
        if response['response'] == 100:
            self.access_token = response['data']['access_token']
            save_access_token(self.access_token)
            time.sleep(0.1)
            return self.getAuthUrl()
        else:
            return print('''
                "账号": %s
                "状态": "登录失败！"
                ''' % self.getName()
                         )

    def auto_login(self):
        read_result = read_access_token()
        if read_result != -1:
            self.access_token = read_result

            headers = {
                'Authorization': f"Bearer {self.access_token}",
                'loginToken': self.access_token,
                'AppVersion': '5.0.1',
                'User-Agent': 'YiBan/5.0.1 Mozilla/5.0 (Linux; Android 10; M2007J3SC Build/QKQ1.200419.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/83.0.4103.101 Mobile Safari/537.36',
                'Host': 'm.yiban.cn',
                'Connection': 'Keep-Alive',
                'Accept-Encoding': 'gzip'
            }
            autologin_url = 'https://m.yiban.cn/api/v4/passport/autologin'

            response = self.sess.get(headers=headers, url=autologin_url).json()
            if response['response'] == 100:
                print('自动登录成功')
                return self.getAuthUrl()

        return self.login()

    def getAuthUrl(self):
        url = "https://f.yiban.cn/iapp/index"
        param = {
            "act": "iapp603148"
        }
        header = {
            "authorization": f"Bearer {self.access_token}",
            "logintoken": self.access_token
        }
        self.sess.get(f"https://f.yiban.cn/iapp603148", headers=header, allow_redirects=False)
        time.sleep(0.1)
        response = self.sess.get(url=url, params=param, headers=header, allow_redirects=False)
        # print(response.status_code)
        verify_url = response.headers['Location']
        # self.verify_request = re.findall(r"verify_request=(.*?)&", self.verify)[0]
        # print(verify_url)
        time.sleep(0.1)
        return self.auth(verify_url)

    def auth(self, verify_url):
        # url = verify_url
        self.sess.headers.update({

            # 'Host': '210.38.250.128:1024',
            'User-Agent': 'YiBan/5.0.1 Mozilla/5.0 (Linux; Android 10; M2007J3SC Build/QKQ1.200419.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/83.0.4103.101 Mobile Safari/537.36',
            "authorization": f"Bearer {self.access_token}",
            "logintoken": self.access_token,
            "Upgrade-Insecure-Requests": "1",
            "X-Requested-With": "com.yiban.app"
        })

        response2 = self.sess.get(url=verify_url, allow_redirects=False)
        response2.encoding = 'utf-8'
        # print(response2.status_code)
        # print(response2.text)
        location_url = response2.headers['Location']
        # print(location_url)
        # print(response2.request.headers)
        self.sess.headers.update({
            "Referer": "http://210.38.250.128:1024/sanythPage/yiban/authorize.html"
        })
        auth__url = "http://210.38.250.128:1024/nonlogin/yiban/authQYY.htm?deviceId=00000000-079c-002e-0033-c5870033c587"
        time.sleep(0.1)
        auth_response = self.sess.get(url=auth__url, allow_redirects=False)
        # print(auth_response.headers)
        # print(auth_response.status_code)
        # if auth_response.status_code == 302:
        #     print("登录成功")
        time.sleep(0.1)
        return self.get_role()

    def get_role(self):
        try:
            get_role_url = "http://210.38.250.128:1024/syt/qywx/home/getRole.htm"
            self.sess.headers.update({
                'Origin': 'http://210.38.250.128:1024',
                'Referer': 'http://210.38.250.128:1024/webApp/xuegong/index.html',

            })

            role_data = self.sess.post(get_role_url)
            # print(role_data.status_code)
            role_data_json = role_data.json()
            print("角色：%s 工号/学号：%s" % (role_data_json['roleName'], role_data_json['userId']))

            # testurl = "http://210.38.250.128:1024/yiban/api/getUserInfo.htm"
            # test_response = self.sess.get(url=testurl)
            # print(test_response.json())
            time.sleep(0.1)
            return self.get_params_fun()
        except requests.exceptions.ConnectionError as result:
            print("获取账号信息出错：%s" % result)
            print("账号: %s\n状态: 广油易学 未授权" % (self.getName() ))


    def get_params_fun(self):

        self.sess.headers.update({
            'Origin': 'http://210.38.250.128:1024',
            'Referer': 'http://210.38.250.128:1024/webApp/xuegong/index.html',

        })

        # 获取type参数
        querylist_url = "http://210.38.250.128:1024/syt/mobile/qywxgroup/querylist.htm"
        # print(querylist_url)
        type_paramsf = self.sess.post(url=querylist_url).text
        # print(type_paramsf)
        time.sleep(0.1)
        # 可切换填表项目
        pattern = re.compile(r'晨午晚检上报/(.*?)",')
        type_params = re.findall(pattern, type_paramsf)[0]

        self.type_params = type_params

        # 获取PDNF参数
        getPDNF_url = "http://210.38.250.128:1024/syt/zzapi/getPDNF.htm"
        PDNF_parmas = self.sess.post(url=getPDNF_url).text

        self.pdnf_parmas = PDNF_parmas

        time.sleep(0.1)

        # 获取id参数
        queryxmqks_url = "http://210.38.250.128:1024/syt/zzapply/queryxmqks.htm"
        queryxmqks_bodyf = {
            "pageIndex": "0",
            "pageSize": "10",
            "type": self.type_params
        }
        self.queryxmqks_bodyf = queryxmqks_bodyf
        queryxmqks_body = urlencode(queryxmqks_bodyf)
        self.sess.headers.update({
            "Referer": "http://210.38.250.128:1024/webApp/xuegong/index.html",
            "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
        })

        # print(queryxmqks_body)
        id_paramsf = self.sess.post(url=queryxmqks_url, data=queryxmqks_body,
                                    allow_redirects=False).json()
        time.sleep(0.1)
        # print(id_paramsf)

        # 可以设置上报类型
        # print("0.个人数据上报\n1.晨午晚检上报\n2.退出脚本")
        # while True:
        #     try:
        #         inp = int(input("输入对应的数字：\n"))
        #         if inp == 0:
        #             break
        #         elif inp == 1:
        #             break
        #         elif inp == 2:
        #             exit()
        #             break
        #         else:
        #             print("请输入正确的数字\n")
        #     except ValueError:
        #         print("输入错误或未输入内容")

        id_params = id_paramsf['data'][0]['id']

        self.id_parmas = id_params
        return self.check_restrict()

    def check_restrict(self):
        # 整合数据
        body = {'xmid': self.id_parmas, 'pdnf': self.pdnf_parmas, 'type': self.type_params}
        # body = json.dumps(body)
        # body = str(body).encode("utf-8")
        check_body = urlencode(body)

        check_url = "http://210.38.250.128:1024/syt/zzapply/checkrestrict.htm"
        check_result = self.sess.post(check_url, data=check_body)
        # print(check_result.text)
        # print(check_result.headers)
        if check_result.headers['Content-Length'] == '0':
            print("今天未填报")
            time.sleep(0.1)
            return self.get_last_data()
        # 已填报提示
        print(check_result.text)

    def get_last_data(self):
        # 获取最近一次提交的数据
        queryxssqlist_url = "http://210.38.250.128:1024/syt/zzapply/queryxssqlist.htm"
        self.queryxmqks_bodyf['xmid'] = self.id_parmas
        queryxssqlist_body = urlencode(self.queryxmqks_bodyf)

        queryxssqlist = self.sess.post(url=queryxssqlist_url, data=queryxssqlist_body).json()
        time.sleep(0.1)
        latest_data = queryxssqlist['data'][0]

        # 获取要提交的问题
        base_apply_info_body_dict = {
            "projectId": self.id_parmas,
            "type": self.type_params
        }
        base_apply_info_body = urlencode(base_apply_info_body_dict)

        base_apply_info_url = "http://210.38.250.128:1024/syt/zzapi/getBaseApplyInfo.htm"
        base_apply_info = self.sess.post(url=base_apply_info_url, data=base_apply_info_body).json()
        time.sleep(0.1)
        # print(base_apply_info)
        base_apply_context = base_apply_info['data']['applyFields']

        #
        sub_data_data = {'xmqkb': {'id': self.id_parmas}}
        # print(sub_data_data)
        # print(base_apply_context)
        # print(latest_data)
        printdata = {}
        print("-" * 10 + "即将要提交的数据-开始" + "-" * 10)

        # 弃用代码
        # for name_item in base_apply_context:
        #     for item in range(1, 101):
        #         # print("c" + str(item))
        #         # print(jdss['c' + str(item)])
        #         if latest_data['c' + str(item)] is not None:
        #             if name_item['fielden'] == 'c%s' % (str(item)):
        #                 sub_data_data['c' + str(item)] = latest_data['c' + str(item)]
        #                 zh_name = name_item['fieldzh']
        #                 zh_context = latest_data['c' + str(item)]
        #                 print("%s ： %s" % (zh_name, zh_context))
        #                 printdata[zh_name] = zh_context

        for q_item in base_apply_context:
            # print(a_json_context['data'][0][])
            question = q_item['fieldzh']
            answer = latest_data.get(q_item['fielden'])
            if answer is not None:
                sub_data_data[q_item['fielden']] = answer
            elif q_item['sfbt'] == '是':
                # print("错误，必填问题没有答案，可能问题已改变，请用APP提交")
                raise Exception("错误，必填问题没有答案，可能问题已改变，请用APP提交")
            answer_opinion = q_item['el']
            if answer_opinion is not None:
                answer_p = "(" + answer_opinion.replace("$", "/") + ")"
                # answer_p = answer_p.replace("$","/")
            else:
                answer_p = ""
            print("%s ：%s" % (question + answer_p, answer))
        # print(sub_data_data)

        print("-" * 10 + "即将要提交的数据-结束" + "-" * 10)
        # print(printdata)

        # print("%s ： %s" %(zh_name,zh_context) )
        # print("-"*20)
        # print("请确认要提交的数据是否有误\n")
        # print("如果有错误，请关闭窗口，手动填写")

        # print("-" * 20)
        # input("按回车键继续")
        # os.system("pause")
        return self.sub_data(sub_data_data)

    def sub_data(self, sub_data_data):
        sub_data_data['type'] = self.type_params
        sub_data_data = json.dumps(sub_data_data)
        sub_data = {'data': sub_data_data,
                    'msgUr': 'syt/zzapply/list.htm?' + 'type=%s&xmid=%s' % (self.type_params, self.id_parmas),
                    'uploadFileStr': {}, 'multiSelectData': {}, 'type': self.type_params}

        sub_data_final = urllib.parse.urlencode(sub_data)

        # print(sub_data_final)
        sub_url = "http://210.38.250.128:1024/syt/zzapply/operation.htm"
        self.sess.headers.update({
            "Accept": "application/json, text/plain, */*"
        })
        sub_response = self.sess.post(url=sub_url, data=sub_data_final)
        # print(sub_response.request.headers)
        # print(sub_response.headers)
        # print(sub_response.text)
        if sub_response.text == 'success':
            print("数据提交成功")
        else:
            # print(sub_response.text)
            print("出错啦")

        # self.check_restrict()


if __name__ == '__main__':
    with open('accounts.json','r',encoding='utf-8') as file:
        min_json = jsmin(file.read())
        yb_env = json.loads(min_json)

    accounts = [
        {
            "account": yb_env['account'],  # 易班账号 ,在 "" 内填写，示例账号为1234567890 ，例如这样填 "account": "1234567890"
            "password": yb_env['password'],  # 易班密码 ,在 "" 内填写，示例密码为password， 例如这样填， "password": "password"
            "remark": "",  # 不用填
            "mail": ""  # 不用填
        }

    ]
    main(accounts)
